package com.light.thread;

import javafx.concurrent.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Consumer;

/**
 * 启用虚拟线程异步执行任务 - 工具类
 * <p>
 * 注意：为了能正确执行 成功和失败 方法，自定义方法中有异常要抛出，不要处理
 * <p>
 * 虚拟线程的应用场景主要包括 IO 密集型任务和高并发 Web 服务器等领域
 * <p>
 * 不支持 CPU 密集型任务、无法直接访问线程本地变量
 */
public final class FxAsyncTask {

    public static final Logger LOGGER = LoggerFactory.getLogger(FxAsyncTask.class);

    /**
     * 异步执行一次
     *
     * @param run
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnce(Run run) {
        return runOnce("异步执行一次", run);
    }

    /**
     * 异步执行一次
     *
     * @param message
     * @param run
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnce(String message, Run run) {
        return runOnce(System.currentTimeMillis(), message, run);
    }

    /**
     * 异步执行一次
     *
     * @param startTime
     * @param message
     * @param run
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnce(long startTime, String message, Run run) {
        return runOnce(startTime, message, run, null);
    }

    /**
     * 异步执行一次
     *
     * @param startTime
     * @param message
     * @param run
     * @param success
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnce(long startTime, String message, Run run, RunSuccess success) {
        return runOnce(startTime, message, run, success, null);
    }

    /**
     * 异步执行一次
     *
     * @param startTime
     * @param message
     * @param run
     * @param success
     * @param fail
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnce(long startTime, String message, Run run, RunSuccess success, RunFail fail) {
        Task<T> task = FxTask.createTask(startTime, message, run, success, fail);
        Thread.startVirtualThread(task);
        return task;
    }

    /**
     * 异步执行一次有返回值
     *
     * @param runBack
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnceBack(RunBack<T> runBack) {
        return runOnceBack("异步执行一次有返回值", runBack);
    }

    /**
     * 异步执行一次有返回值
     *
     * @param message
     * @param runBack
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnceBack(String message, RunBack<T> runBack) {
        return runOnceBack(System.currentTimeMillis(), message, runBack);
    }

    /**
     * 异步执行一次有返回值
     *
     * @param startTime
     * @param message
     * @param runBack
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnceBack(long startTime, String message, RunBack<T> runBack) {
        return runOnceBack(startTime, message, runBack, null);
    }

    /**
     * 异步执行一次有返回值
     *
     * @param startTime
     * @param message
     * @param runBack
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnceBack(long startTime, String message, RunBack<T> runBack, Consumer<T> success) {
        return runOnceBack(startTime, message, runBack, success, null);
    }

    /**
     * 异步执行一次有返回值
     *
     * @param startTime
     * @param message
     * @param runBack   要处理的方法
     * @param success   成功后执行的方法
     * @param fail      失败后执行的方法
     * @param <T>
     * @return
     */
    public static <T> Task<T> runOnceBack(long startTime, String message, RunBack<T> runBack, Consumer<T> success, Consumer<T> fail) {
        Task<T> task = FxTask.createTaskBack(startTime, message, runBack, success, fail);
        Thread.startVirtualThread(task);
        return task;
    }

    public static <T> void runOnceTask(String message, Task<T> task) {
        LOGGER.info("Task {} 开始执行", message);
        Thread.startVirtualThread(task);
    }
}
